using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace GP2D3D_Huiswerk2_RickBeijer_S1012261
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class FireAnt : Microsoft.Xna.Framework.DrawableGameComponent
    {
        private static readonly Vector3 BASE_DIRECTION = new Vector3(0, 12, 0);
        private static readonly Vector3 BASE_OFFSET = new Vector3(0, 16, 0);
        private SpriteBatch spriteBatch;
        private Texture2D image;
        private static List<KeyValuePair<Vector2, Rectangle>> frames;
        private int currentFrame;
        private int rotation;
        private Point location;
        private int updates;
        private bool isKeySpaceDown;
        private bool isShooting;

        public FireAnt(Game game, SpriteBatch spriteBatch, Point location)
            : base(game)
        {
            this.spriteBatch = spriteBatch;
            this.image = game.Content.Load<Texture2D>( "Fire Ant Animated" );

            if (frames == null)
            {
                frames = new List<KeyValuePair<Vector2, Rectangle>>();
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 14, 6, 48, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 66, 7, 47, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 124, 55, 47, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 12, 54, 47, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 67, 54, 47, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 120, 7, 47, 36 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 176, 57, 47, 35 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 18 ), new Rectangle( 99, 105, 47, 32 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 16 ), new Rectangle( 177, 7, 47, 31 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 18 ), new Rectangle( 99, 105, 47, 32 ) ) );
                frames.Add( new KeyValuePair<Vector2, Rectangle>( new Vector2( 23, 21 ), new Rectangle( 176, 57, 47, 35 ) ) );
            }

            this.currentFrame = 0;
            this.rotation = 0;
            this.location = location;
            this.updates = 0;
            this.isKeySpaceDown = false;
            this.isShooting = false;
        }

        public override void Update(GameTime gameTime)
        {
            // Don't turn every update.
            updates++;

            if (updates > 100)
            {
                updates = 0;
            }

            KeyboardState keyboardstate = Keyboard.GetState();

            if (keyboardstate.IsKeyDown(Keys.Space) && !isShooting)
            {
                // Shoot
                isShooting = true;
                currentFrame = 6;
            }
            if (keyboardstate.IsKeyDown(Keys.Left) && updates % 5 == 0)
            {
                // Turn counter clockwise
                rotation -= 10;

                if (rotation < 0)
                {
                    rotation += 360;
                }
            }
            if (keyboardstate.IsKeyDown(Keys.Right) && updates % 5 == 0)
            {
                // Turn Clockwise
                rotation += 10;

                if (rotation > 360)
                {
                    rotation -= 360;
                }
            }

            isKeySpaceDown = keyboardstate.IsKeyDown(Keys.Space);

            // Keep animating, but not every update
            if (updates % 8 == 0)
            {
                currentFrame++;
            }

            if (isShooting)
            {
                // When the right shooting frame is displayed, shoot the actual projectile
                // (To prevent shooting it multiple times, take the updates into account)
                if (currentFrame == 8 && updates % 8 == 0)
                {
                    // Rotate the baseoffset the projectile should have on the base image. This will be the projectile's initial location
                    Vector3 rotatedOffset = Vector3.Transform( BASE_OFFSET, Matrix.CreateRotationZ( MathHelper.ToRadians( rotation ) ) );
                    // Rotate the point where the projectile should first spawn
                    Point position = new Point( location.X + (int) ( ( rotatedOffset.X ) + 0.5 ),
                                                location.Y + (int) ( ( rotatedOffset.Y ) + 0.5 ) );
                    // Rotate the basedirection the image has, so that it matches with the rotation of the Ant. This will be the projectile's velocity
                    Vector3 rotatedDirection = Vector3.Transform( BASE_DIRECTION, Matrix.CreateRotationZ( MathHelper.ToRadians( rotation ) ) );

                    // Add the projectile to the ProjectileList
                    ( (IProjectileList) Game.Services.GetService( typeof(IProjectileList) ) ).AddProjectile( position, rotatedDirection );
                }
                        // If the shooting animation is over, return to normal animation
                else if (currentFrame >= 11)
                {
                    isShooting = false;
                    currentFrame = 0;
                }
            }
            else
            {
                // Last 5 frames are reserved for shooting, so cap animation at 7 frames (frame 6 is used in both)
                if (currentFrame >= 7)
                {
                    currentFrame = 0;
                }
            }

            base.Update(gameTime);
        }

        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Begin();
            spriteBatch.Draw( image,
                              new Rectangle( location.X,
                                             location.Y,
                                             frames[currentFrame].Value.Width,
                                             frames[currentFrame].Value.Height ),
                              frames[currentFrame].Value,
                              Color.White,
                              MathHelper.ToRadians( rotation ),
                              frames[currentFrame].Key,
                              SpriteEffects.None,
                              1 );
            spriteBatch.End();

            base.Draw( gameTime );
        }
    }
}